package com.grow.greenhouse.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.grow.greenhouse.common.ErrorCode;
import com.grow.greenhouse.domain.Shedmember;
import com.grow.greenhouse.domain.User;
import com.grow.greenhouse.domain.request.AddMemberRequest;
import com.grow.greenhouse.exception.BusinessException;
import com.grow.greenhouse.mapper.UserMapper;
import com.grow.greenhouse.once.UserContext;
import com.grow.greenhouse.service.ShedmemberService;
import com.grow.greenhouse.service.UserService;
import com.grow.greenhouse.utils.JwtUtil;
import com.grow.greenhouse.utils.MailUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.grow.greenhouse.constant.UserConstant.USER_LOGIN_STATE;

/**
* @author 23854
* @description 针对表【user】的数据库操作Service实现
* @createDate 2024-01-28 18:45:00
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{
    //盐值混淆密码
    private  static final String SALT = "GuQin";
    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private MailUtil mailUtil;

    @Resource
    private ShedmemberService shedmemberService;

    @Resource
    private Gson gson;

    @Override
    public void sendEmailVerifyCode(String email){
        if(StringUtils.isBlank(email)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱为空");
        }
        // 邮箱验证的正则表达式
        String EMAIL_PATTERN = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        Pattern pattern = Pattern.compile(EMAIL_PATTERN);
        Matcher matcher = pattern.matcher(email);

        if(!matcher.matches()) {
            log.info("userLogin failed, userAccount does not match email format");
            throw new BusinessException(ErrorCode.WRONG_ACCOUNT,"账号格式不正确，应为有效邮箱");
        }
        String redisKey = String.format("greenHouse.user.emailVeryCode.%s",email);
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String verifyCode = this.getVerifyCode();
        valueOperations.setIfAbsent(redisKey, verifyCode,300000, TimeUnit.MILLISECONDS);
        mailUtil.sendHtmlMail(email,"种植云平台邮箱验证码",verifyCode);
    }


    @Override
    public Map<String,Object> userRegister(String userName,String userVeryCode,String userAccount, String userPassword) {
        //1.校验
        if(StringUtils.isAnyBlank(userName,userAccount,userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数为空");
        }


        // 邮箱验证的正则表达式
        String EMAIL_PATTERN = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        Pattern pattern = Pattern.compile(EMAIL_PATTERN);
        Matcher matcher = pattern.matcher(userAccount);

        if(!matcher.matches()) {
            log.info("userLogin failed, userAccount does not match email format");
            throw new BusinessException(ErrorCode.WRONG_ACCOUNT,"账号格式不正确，应为有效邮箱");
        }

        String redisKey = "greenHouse.user.emailVeryCode."+userAccount;
        //用户输入的验证码与实际验证码是否一致
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String veryCode = valueOperations.get(redisKey).toString();
        if(StringUtils.isBlank(redisKey)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱验证码已过期，请重新输入");
        }
        if(!StringUtils.equals(veryCode,userVeryCode))
        {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱验证码错误，请重新输入");
        }

        //账户不能重复
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.eq(User::getAccount,userAccount);
        long count = this.count(lqw);
        if(count > 0){
            throw new BusinessException(ErrorCode.IS_EXISTS,"账户不能重复");
        }

        //对密码进行加密
        //在此处可以进行加盐操作(即将加密内容进行进一步的混淆，鱼皮语录：搅屎棍)

        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());


        //插入数据
        User user = new User();
        user.setUserName(userName);
        user.setAccount(userAccount);
        user.setPassword(encryptPassword);
        boolean saveResult = this.save(user);

        if(!saveResult){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"插入数据异常");
        }
        User safeUser = this.getSafeUser(user);
        //记录用户的登录态
        Map<String, Object> map = new HashMap<>();
        try{

            // 生成token

            String token = JwtUtil.createToken(user.getId());

            map.put("status", true);
            map.put("msg", "登录成功");
            map.put("token", token); // 响应token，存储在客户端
        }catch (Exception e) {
            log.info("登录失败...");
            map.put("status", false);
            map.put("msg", "登录失败");
        }
        return map;
    }

    @Override
    public Map<String,Object> userLogin(String userAccount, String userPassword, HttpServletRequest request) {
        //1.校验
        if(StringUtils.isAnyBlank(userAccount,userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号或密码不能为空");
        }

        // 邮箱验证的正则表达式
        String EMAIL_PATTERN = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        Pattern pattern = Pattern.compile(EMAIL_PATTERN);
        Matcher matcher = pattern.matcher(userAccount);

        if(!matcher.matches()) {
            log.info("userLogin failed, userAccount does not match email format");
            throw new BusinessException(ErrorCode.WRONG_ACCOUNT,"账号格式不正确，应为有效邮箱");
        }

        //对密码进行加密
        //在此处可以进行加盐操作(即将加密内容进行进一步的混淆，鱼皮语录：搅屎棍)
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        //查询用户是否存在
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getAccount,userAccount).eq(User::getPassword,encryptPassword);
        User user = this.getOne(lqw);

        //用户不存在
        if(user == null){
            log.info("userLogin failed, userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.WRONG_PWD,"账户密码不匹配");
        }

        UserContext.setUserId(user.getId());
        log.info(String.valueOf(Thread.currentThread().getId()));
        //用户脱敏

        User safeUser = getSafeUser(user);
        //记录用户的登录态
        // 生成token
        String token = JwtUtil.createToken(user.getId());

        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("user",safeUser);
        returnMap.put("token",token);
        return returnMap;
    }


    private String getVerifyCode(){
        return  Integer.toString((int) (Math.random() * 900000) + 100000);
    }

    @Override
    public User getSafeUser(User originUser) {
        if(originUser == null)
            return null;
        User safeUser = new User();
        safeUser.setId(originUser.getId());
        safeUser.setUserName(originUser.getUserName());
        safeUser.setAccount(originUser.getAccount());
        safeUser.setShedName(originUser.getShedName());
        safeUser.setUserRole(originUser.getUserRole());
        safeUser.setAvatarUrl(originUser.getAvatarUrl());
        return safeUser;
    }

    @Override
    public int userLogout(HttpServletRequest request) {
        //移除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return 1;
    }



    @Override
    public int updateUser(User user, User LoginUser) {
        long userId = user.getId();
        if(userId <= 0L)
        {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        if(LoginUser.getId()!=userId)
        {
            throw new BusinessException(ErrorCode.NO_AUTH);
        }
        User oldUser = userMapper.selectById(userId);
        if(oldUser == null)
        {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        return userMapper.updateById(user);
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        String token = request.getHeader("token");
        if(token == null)
            return null;
        if(!JwtUtil.verifyToken(token)){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"Token验证失败，请登录");
        }
        long userId = Long.parseLong(JwtUtil.getUserIdFromToken(token));
        if(userId <= 0){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"用户id应为正数");
        }
        User userObj = this.getById(userId);
        if(userObj == null)
        {
            throw new BusinessException(ErrorCode.NOT_LOGIN,"未查询到用户，请重新登录");
        }
        return userObj;
    }

    @Override
    public Map<String,List<User>> getMembers(HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        Long userId = loginUser.getId();
        QueryWrapper<Shedmember> queryWrapper = new QueryWrapper<>();
        Map<String,List<User>> userMap = new HashMap<>();
        //如果当前用户是棚主
        if(loginUser.getUserRole() == 1)
        {
            queryWrapper.eq("ownerid",userId);
            List<User> memberList = getMemberList(queryWrapper);
            userMap.put("owner", Stream.of(new User[]{loginUser}).collect(Collectors.toList()));
            userMap.put("member",memberList);
        }
        //当前用户仅为成员，需要先把他的棚主查出来然后根据棚主再去查
        else
        {
            queryWrapper.eq("memberid",userId);
            Shedmember shedmember = shedmemberService.getOne(queryWrapper);
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ownerid",shedmember.getOwnerid());
            List<User> memberList = getMemberList(queryWrapper);
            User owner = this.getById(shedmember.getOwnerid());
            userMap.put("owner",Stream.of(new User[]{owner}).collect(Collectors.toList()));
            userMap.put("member",memberList);
        }
        return userMap;
    }

    @Override
    public String addMembers(AddMemberRequest addMemberRequest, HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        if(loginUser.getUserRole() != 1){
            throw new BusinessException(ErrorCode.NO_AUTH,"当前用户不是棚主，无法添加成员");
        }
        String userAccount = addMemberRequest.getUserAccount();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account",userAccount);
        User newMember = this.getOne(queryWrapper);
        if(newMember == null)
        {
            throw new BusinessException(ErrorCode.NULL_ERROR,"未查询到有此用户，请检查邮箱账号是否输入正确");
        }
        Shedmember shedmember = new Shedmember();
        shedmember.setOwnerid(loginUser.getId());
        shedmember.setMemberid(newMember.getId());
        boolean save = shedmemberService.save(shedmember);
        if(!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"新增失败");
        }
        return "添加成功";

    }


    private List<User> getMemberList(QueryWrapper<Shedmember> queryWrapper) {
        List<Shedmember> list = shedmemberService.list(queryWrapper);
        List<Long> memberIdList = list.stream()
                .map(Shedmember::getMemberid)
                .collect(Collectors.toList());
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.in("id",memberIdList);
        return this.list(userQueryWrapper);
    }
}




